// @import
import Time from "../base/Time";

/**
 * Cd 计时器, 
 * 通过比对时间戳来控制时间间隔
 */
export default class CdTimer {
    /**
     * 阈值
     */
    private readonly _nThreshold: number;

    /**
     * 开始时间
     */
    private _nStartTime: number;

    /**
     * 额外时间
     */
    private _nExtraTime: number;

    /**
     * 类参数构造器
     * 
     * @param nThreshold 阈值, 单位 = 秒. 累加时间超过这个值之后, Cd 过热, 就不能再向上累计了
     */
    public constructor(nThreshold: number = 0.001) {
        if (nThreshold <= 0) {
            throw new Error("nThreshold <= 0");
        }

        this._nThreshold = nThreshold;
    }

    /**
     * 获取阈值
     * 
     * @returns 阈值
     */
    public getThreshold(): number {
        return this._nThreshold;
    }

    /**
     * 获取额外时间
     * 
     * @returns 额外时间
     */
    public getExtraTime(): number {
        return this._nExtraTime;
    }

    /**
     * 获取阈值 + 额外时间
     * 
     * @returns 阈值 + 额外时间
     */
    public getThresholdAndExtraTime(): number {
        return this.getThreshold() + this.getExtraTime();
    }

    /**
     * 填满 Cd
     * 
     * @param nExtraTime 额外时间
     * @returns this 指针
     */
    public fill(nExtraTime: number = 0): CdTimer {
        this._nStartTime = CdTimer.getCurrTime();
        this._nExtraTime = nExtraTime;
        return this;
    }

    /**
     * ( 协程方式 ) 等待
     * 
     * @returns 生成器
     */
    public *wait_XC(): Generator<boolean> {
        while (this.isHot()) {
            yield true;
        }

        yield false;
    }

    /**
     * 获取剩余时间
     * 
     * @returns 剩余时间
     */
    public getRemainTime(): number {
        return (this._nStartTime + this._nExtraTime + this._nThreshold) - CdTimer.getCurrTime();
    }

    /**
     * 是否过热?
     * 
     * @returns true = 过热, 还在冷却中; false = 冷却完毕
     */
    public isHot(): boolean { 
        return this.getRemainTime() > 0;
    }

    /**
     * 重置
     * 
     * @returns this 指针
     */
    public reset(): CdTimer {
        this._nStartTime = 0;
        this._nExtraTime = 0;
        return this;
    }

    /**
     * 获取当前时间
     * 
     * @returns 当前时间
     */
    private static getCurrTime(): number {
        return Time.getTime();
    }
}
